﻿using System;
using System.Collections.Generic;
using System.Linq;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using VSIXUtilities.Helpers.Extensions;
using VSIXUtilities.DataObjects;

namespace VSIXUtilities.Helpers
{
    public class CodeElementHelper
    {
        DTE DTEInstance;
        List<CodeElement> ListOfCurrentCodeElements = new List<CodeElement>();
        int CurrentLine;

        public CodeElementHelper()
        {
            this.DTEInstance = (DTE)ServiceProvider.GlobalProvider.GetService(typeof(SDTE));
        }

        public CodeElement[] GetCurrentElements()
        {
#warning GetCurrentElements should search based on absolute character offset insetead of line number for more accurate results.
            ListOfCurrentCodeElements.Clear();
            CurrentLine = ((TextSelection)DTEInstance.ActiveDocument.Selection).ActivePoint.Line;

            FileCodeModel fcm = DTEInstance.ActiveDocument.ProjectItem.FileCodeModel;
            foreach (CodeElement CodeElementInstance in fcm.CodeElements)
            {
                GetCurrentElements(CodeElementInstance);
            }
            return ListOfCurrentCodeElements.ToArray();
        }

        private void GetCurrentElements(CodeElement CodeElementInstance)
        {
            if (CodeElementInstance.StartPoint.Line <= CurrentLine && CodeElementInstance.EndPoint.Line >= CurrentLine)
            {
                ListOfCurrentCodeElements.Add(CodeElementInstance);
                if (CodeElementInstance.CanHaveDoumentableChildren())
                {
                    foreach (CodeElement CodeElementChild in CodeElementInstance.Children)
                    {
                        GetCurrentElements(CodeElementChild);
                    }
                }
            }
        }

        List<IVsHierarchyWrapper> NamespaceContainers = new List<IVsHierarchyWrapper>();
        public IVsHierarchyWrapper[] SearchForNamespace(IVsHierarchyWrapper ItemToSearchIn, CodeElement CodeElementNamespace)
        {
            NamespaceContainers.Clear();
            SearchForNamespaceCore(ItemToSearchIn, CodeElementNamespace);
            return NamespaceContainers.ToArray();
        }
        private void SearchForNamespaceCore(IVsHierarchyWrapper ItemToSearchIn, CodeElement CodeElementNamespace)
        {
            if (ItemToSearchIn.IsProjectItem && ItemToSearchIn.CanBeDocCommented())
            {
                //EnvDTE.DTE ddd = (DTE)ServiceProvider.GlobalProvider.GetService(typeof(SDTE));
                //bool aaa = ddd.ItemOperations.IsFileOpen(Item.FilePath);
                ProjectItem ProjectItemInstance = ItemToSearchIn.ToProjectItem();
                if (ProjectItemInstance.GetBuildAction() == VSLangProj.prjBuildAction.prjBuildActionCompile && DoesFileCodeModelContainsNamespace(ProjectItemInstance.FileCodeModel, CodeElementNamespace.FullName))
                {
                    NamespaceContainers.Add(ItemToSearchIn);
                }
            }
            else
            {
                foreach (IVsHierarchyWrapper IVsHierarchyWrapperChild in ItemToSearchIn.Children)
                {
                    SearchForNamespaceCore(IVsHierarchyWrapperChild, CodeElementNamespace);
                }
            }
        }
        public bool DoesFileCodeModelContainsNamespace(FileCodeModel FileCodeModelToSearchIn, string NamespaceFullName)
        {
            foreach (CodeElement CodeElementInstance in FileCodeModelToSearchIn.CodeElements)
            {
                if (DoesCodeElementContainsNamespace(CodeElementInstance, NamespaceFullName))
                {
                    return true;
                }
            }
            return false;
        }
        public bool DoesCodeElementContainsNamespace(CodeElement CodeElementToSearchIn, string NamespaceFullName)
        {
            if (CodeElementToSearchIn.Kind == vsCMElement.vsCMElementNamespace)
            {
                if (CodeElementToSearchIn.FullName == NamespaceFullName)
                {
                    return true;
                }
                else if (NamespaceFullName.StartsWith(CodeElementToSearchIn.FullName))
                {
                    foreach (CodeElement CodeElementChild in CodeElementToSearchIn.Children)
                    {
                        if (DoesCodeElementContainsNamespace(CodeElementChild, NamespaceFullName))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

    }
}
